今天,筆者將跟著google所製作的教學一起學習製作人生中第一個App:一個簡單,隨機選擇兩個英文文字並將他們合併,且使用者可以儲存喜歡的生成詞語。當然,因為是使用Flutter製作的,所以能夠在Android, Web, Linux等平台上運作。
本篇裡,筆者將使用NeoVim實做,並會記下自己的過程,供大家參考。
Codelab教學連結
flutter device
設定目標平台。首先,在Terminal中輸入以下程式碼,以建立一個全新的專案。專案名字可以自行依心情設定。
flutter create first_app
如同上次我們建立測試執行檔test_drive,此時它也幫我們建立好一個名為first_app的資料夾。資料夾的結構如下:
圖片中所開啟的檔案lib/main.dart便是我們專案主要編輯的檔案。
pubspec.yaml存有著我們所編輯中專案的一些基本資訊,如名稱、版本、所需資料庫等等的內容。
為了增加我們應用程式中所有的英文單字,我們需要到此檔案中更改一些設定。
到檔案中dependencies(第30行)項增加英文單字的packages:
dependencies:
flutter:
sdk: flutter
english_words: ^4.0.0
provider: ^6.0.0
此檔案適用於設定Flutter在分析我們的檔案時所需要的一些規則,現在所條的設定十分寬鬆,考量到這是我們的第一次實做,之後隨時都可以更改這裡的設定,將它變得更嚴謹。
我們開啟analysis_options.yaml,增加一些linter rules:
include: package:flutter_lints/flutter.yaml
linter:
rules:
avoid_print: false
prefer_const_constructors_in_immutables: false
prefer_const_constructors: false
prefer_const_literals_to_create_immutables: false
prefer_final_fields: false
unnecessary_breaks: true
use_key_in_widget_constructors: false
在開始編輯main.dart之前,可以先跑一次flutter test
,這會測試我們更改yaml檔後程式是否可以正確執行,並下載剛剛於pubspec.yaml檔增加的packages,方便我們編輯時的autocompletion運作。
開啟我們的lib/main.dart,並將檔案中的程式碼由以下內容取代:
import 'package:english_words/english_words.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => MyAppState(),
child: MaterialApp( //sets the theme/look of the app
title: 'Namer App',
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepOrange),
),
home: MyHomePage(),
),
);
}
}
class MyAppState extends ChangeNotifier {
var current = WordPair.random();
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
var appState = context.watch<MyAppState>();
return Scaffold(
body: Column(
children: [
Text('A random idea:'),
Text(appState.current.asLowerCase),
],
),
);
}
}
p.s. 此時如果我們去執行flutter test
做測試,會顯示出:Conter increments smoke test Test faild.
,但使用flutter run
卻能夠正常執行,可以想想看是為什麼呢~
我們來建立一個用於生成下一組隨機詞組的按鈕:Next
在main.dart檔案最下方class MyHomePage的Scaffold中增加ElevatedButton,如下方所示:
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
var appState = context.watch<MyAppState>();
return Scaffold(
body: Column(
children: [
Text('A random idea:'),
Text(appState.current.asLowerCase),
ElevatedButton(onPressed: () {
print('button pressed!');
},
child: Text('Next'),
)
],
),
);
}
}
我們此時執行flutter run
時,便能看到我們的小程式有了個按鈕,每次按了按鈕,雖然在應用程式的界面上看不到什麼改變,但在__FLUTTER_DEV_LOG__中都會印出'button pressed!'的字樣。
想給我們的按鈕增加功能,我們要在class MyAppState extends ChangeNotifier中增加一個函式:getNext(),顧名思義,就是獲得下一個詞組。
class MyAppState extends ChangeNotifier {
var current = WordPair.random();
void getNext() {
current = WordPair.random();
notifyListeners();
}
}
我們還需要讓按鈕被按下時呼叫函式。記得我們在前面建立按鈕時讓它被按下時印出'button pressed!'嗎?此時,我們只需要在那行之上呼叫appState.getNext(),便能夠顯示下一個隨機詞組。
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
var appState = context.watch<MyAppState>();
return Scaffold(
body: Column(
children: [
Text('A random idea:'),
Text(appState.current.asLowerCase),
ElevatedButton(onPressed: () {
appState.getNext();
print('button pressed!');
},
child: Text('Next'),
)
],
),
);
}
}
在執行`flutter run時,筆者稍稍更改了按鈕上的文字,而不須重開應用程式,我們的app立刻就顯示出剛剛所作的更新內容,是不是很方便,能即時看到改變!這也是Flutter在開發時我們可以使用的一大優勢之一。
因為顯示問題,在markdown程式碼區塊無法顯示dart的程式碼,因此部份區塊未設定程式碼語言,若閱讀造成不便,敬請見諒m(__)m
今天分享的內容就到這裡啦,明天我們將會在這個應用程式中做出更多的延伸,增加可儲存喜歡的詞組這個功能,以及美化應用程式。若有任何想法,都歡迎留言或email,謝謝今天讀到這裡的讀者,我們明天見!
此時如果我們去執行flutter test做測試,會顯示出:Conter increments smoke test Test faild.,但使用flutter run卻能夠正常執行,可以想想看是為什麼呢~
答案是什麼呢?
test是用於測試在執行時有沒有可能會產生讓程式crash的錯誤,並不代表無法程式跑不動。
Smoke Test這個詞的來源有個說法是從硬體而來:「如果裝置被啟動了,會不會冒煙出問題?」並在冒煙時就先解決問題避免產生更大的損失(裝置燒起來)。但裝置冒煙時還是可以運作的,只是它之後可能就會壞掉。
關於smoke test是參考以下文章內容:
做到這一步,按Next,上面的英文會改變嗎?
會哦!在這程式中生成的英文詞組是存在appState
的current
中,而使用appState.getNext()
便會更改current
所存的內容。